using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Assignment1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private Texture2D ball;
        private Texture2D padLeft;
        private Texture2D padRight;
        private Texture2D pauseScreen;

        private Vector2 velocity;

        private Vector2 ballPos;
        private Vector2 ballRadius;
        private Vector2 ballPosZero;

        private Vector2 padPos1;
        private Vector2 padPos2;

        private Vector2 screenDimension;
        private SpriteFont font;
        private float teamALength;
        private float teamBLength;

        private string pauseString;
        private Vector2 pausePosition;

        private int scoreA;
        private int scoreB;

        private GamePadState gPad1;
        private GamePadState gPad2;

        private GamePadState oldGPad1;
        private GamePadState oldGPad2;

        private bool isPause;

        private KeyboardState state;
        private KeyboardState oldState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            isPause = true;

            ball = Content.Load<Texture2D>("img/ball");
            padLeft = Content.Load<Texture2D>("img/left");
            padRight = Content.Load<Texture2D>("img/right");

            screenDimension = new Vector2(graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);

            ballRadius = new Vector2(ball.Width, ball.Height) / 2;

            ballPosZero = screenDimension / 2 - ballRadius;
            ballPos = ballPosZero;

            padPos1 = new Vector2(0, screenDimension.Y / 2 - 50);
            padPos2 = new Vector2(screenDimension.X - 20, screenDimension.Y / 2 - 50);

            font = Content.Load<SpriteFont>("font");
            teamALength = font.MeasureString("Team A").X / 2;
            teamBLength = font.MeasureString("Team B").X / 2;

            velocity = new Vector2(5);

            scoreA = 0;
            scoreB = 0;

            CreateRectangle((int)screenDimension.X, (int)screenDimension.Y,out pauseScreen);
#if WINDOWS
            pauseString = "Game paused. Press Enter to resume";
#elif XBOX
            pauseString="Game paused. Press Start to resume";
#endif
            pausePosition = screenDimension / 2 - font.MeasureString(pauseString) / 2;

            state = Keyboard.GetState();
            oldState = state;

            base.Initialize();

        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);



            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            if (state.IsKeyDown(Keys.Escape))
                this.Exit();
            

            // TODO: Add your update logic here
            gPad1 = GamePad.GetState(PlayerIndex.One);
            gPad2 = GamePad.GetState(PlayerIndex.Two);
            state = Keyboard.GetState();

            PauseListener();
            if (!isPause)
            {
#if !XBOX
                if (gPad1.IsConnected)
                {
                    if (gPad2.IsConnected)
                    {
                        HandlleGamepad(gPad1.ThumbSticks.Left.Y, ref padPos1.Y);
                        HandlleGamepad(gPad2.ThumbSticks.Left.Y, ref padPos2.Y);
                    }
                    else
                    {
                        HandlleGamepad(gPad1.ThumbSticks.Left.Y, ref padPos1.Y);
                        HanndleKeyboard(ref padPos2.Y, true);
                    }
                }
                else
                {
                    HanndleKeyboard(ref padPos1.Y, false);
                    HanndleKeyboard(ref padPos2.Y, true);
                }
#else
            if (gPad2.IsConnected)
            {
                HandlleGamepad(gPad1.ThumbSticks.Left.Y, ref padPos1.Y);
                HandlleGamepad(gPad2.ThumbSticks.Left.Y, ref padPos2.Y);
            }
            else
            {
                HandlleGamepad(gPad1.ThumbSticks.Left.Y, ref padPos1.Y);
                HandlleGamepad(gPad1.ThumbSticks.Right.Y, ref padPos2.Y);
            }
#endif

                UpdateBall();
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            spriteBatch.Begin();
            spriteBatch.Draw(padLeft, padPos1, Color.White);
            spriteBatch.Draw(padRight, padPos2, Color.White);
            spriteBatch.Draw(ball, ballPos, Color.White);
            spriteBatch.DrawString(font, "Team A\n   " + scoreA, new Vector2(screenDimension.X / 4 - teamALength, 10), Color.Chocolate);
            spriteBatch.DrawString(font, "Team B\n   " + scoreB, new Vector2(screenDimension.X * 3 / 4 - teamBLength, 10), Color.Chocolate);
            if (isPause)
            {
                spriteBatch.Draw(pauseScreen, new Vector2(0, 0), Color.White * 0.5f);
                spriteBatch.DrawString(font, pauseString, pausePosition, Color.Black);
            }
            spriteBatch.End();

            base.Draw(gameTime);
        }

        private void UpdateBall()
        {

            if ((ballPos.Y < padPos1.Y + 100 && ballPos.Y > padPos1.Y) && (ballPos.X < 20))
                velocity.X *= -1;
            if ((ballPos.Y < padPos2.Y + 100 && ballPos.Y > padPos2.Y) && (ballPos.X > screenDimension.X - ballRadius.X * 2 - 20))
                velocity.X *= -1;
            if (ballPos.X < 0)
            {
                scoreB++;
                ballPos = ballPosZero;
                velocity *= -1;
            }
            if (ballPos.X > screenDimension.X - ballRadius.X * 2)
            {
                scoreA++;
                ballPos = ballPosZero;
                velocity *= -1;
            }
            //  velocity.X *= -1;
            if (ballPos.Y < 0 || ballPos.Y > screenDimension.Y - ballRadius.Y * 2)
                velocity.Y *= -1;
            ballPos += velocity;
        }

        private void HandlleGamepad(float stickY, ref float tmpY)
        {
            if (tmpY >= 0 && tmpY <= screenDimension.Y - 100)
            {
                tmpY -= stickY * 5;
            }
            tmpY = (tmpY < 0) ? 0 : tmpY;
            tmpY = (tmpY > screenDimension.Y - 100) ? screenDimension.Y - 100 : tmpY;
        }
        private void HanndleKeyboard(ref float tmpY, bool isPlayer2)
        {
            if (isPlayer2)
            {

                if (tmpY > 0 && state.IsKeyDown(Keys.Up))
                {
                    tmpY -= 5;
                }
                tmpY = (tmpY < 0) ? 0 : tmpY;
                if (tmpY < screenDimension.Y - 100 && state.IsKeyDown(Keys.Down))
                {
                    tmpY += 5;
                }
                tmpY = (tmpY > screenDimension.Y - 100) ? screenDimension.Y - 100 : tmpY;
            }
            else
            {
                if (tmpY > 0 && state.IsKeyDown(Keys.W))
                {
                    tmpY -= 5;
                }
                tmpY = (tmpY < 0) ? 0 : tmpY;
                if (tmpY < screenDimension.Y - 100 && state.IsKeyDown(Keys.S))
                {
                    tmpY += 5;
                }
                tmpY = (tmpY > screenDimension.Y - 100) ? screenDimension.Y - 100 : tmpY;
            }
        }

        public void PauseListener()
        {
            if ((state.IsKeyDown(Keys.Enter) && oldState.IsKeyUp(Keys.Enter)) || (gPad1.IsButtonDown(Buttons.Start) && oldGPad1.IsButtonUp(Buttons.Start)) || (gPad2.IsButtonDown(Buttons.Start) && oldGPad2.IsButtonUp(Buttons.Start)))
            {
                isPause = !isPause;
            }
            oldState = state;
            oldGPad1=gPad1;
            oldGPad2=gPad2;
        }

        public void CreateRectangle(int width, int height, out Texture2D rectangleTexture)
        {
            // create the rectangle texture, ,but it will have no color! lets fix that
            rectangleTexture = new Texture2D(GraphicsDevice, width, height, false, SurfaceFormat.Color);

            // set the color to the amount of pixels
            Color[] color = new Color[width * height];

            // loop through all the colors setting them to whatever values we want
            for (int i = 0; i < color.Length; i++)
            {
                color[i] = new Color(255, 255, 255);
            }

            // set the color data on the texture
            rectangleTexture.SetData(color);

        }


    }
}
